using UnityEngine;
using System.Collections;

/// \class  gkBoostComponent
/// \brief  Help to manage the application of velocity boost
[AddComponentMenu("GK/Engine/GameCore/Movement/gkBoostComponent")]
[RequireComponent (typeof (gkVelocityController))]
public class gkBoostComponent : MonoBehaviour 
{	
    /// The normal velocity at which we have to return when the boost is over
    private Vector3 m_f3NormalVelocity;

    /// The duration of the transition from the boost velocity to the normal velocity
    ///             If < 0  : Keep the default acceleration
    ///             If == 0 : Reach the desired velocity immediately 
    private float m_fReturnToNormalVelocityDuration = -1.0f;

    /// The owner velocity controller
    private gkVelocityController m_rVelocityController;

    /// The boost time left
    private float m_fBoostTimeLeft;

    ///Is the boost infinite
    private bool m_bInfinite;

    /// Are we boosting
    private bool m_bBoosting;
	
	/// The event component
	private gkEventComponent m_rEventComponent;

    /// \brief  Reach a velocity with a maximum acceleration 
    /// \warning  Each call replace the other
    /// \param[in]  a_fBoostDuration : 
    ///             If < 0  : Infinite
    /// \param[in]  a_fReachVelocityDuration  The duration of the transition from the normal velocity to the boost velocity
    ///             If < 0  : Keep the default acceleration
    ///             If == 0 : Reach the desired velocity immediately 
    /// \param[in]  a_fReturnToNormalVelocityDuration  The duration of the transition from the boost velocity to the normal velocity
    ///             If < 0  : Keep the default acceleration
    ///             If == 0 : Reach the desired velocity immediately 
    public void Boost(Vector3 a_f3NormalVelocity, Vector3 a_f3BoostVelocity, float a_fBoostDuration,
	    float a_fReachVelocityDuration = -1.0f, float a_fReturnToNormalVelocityDuration = -1.0f)
    {

	    m_f3NormalVelocity = a_f3NormalVelocity;
	    m_fReturnToNormalVelocityDuration = a_fReturnToNormalVelocityDuration;
	    m_fBoostTimeLeft = a_fBoostDuration;
	    if(m_fBoostTimeLeft < 0.0f)
	    {
		    m_bInfinite = true;
	    }
	    else
	    {
		    m_bInfinite = false;
	    }
	    m_bBoosting = true;

	    m_rVelocityController.SetDesiredVelocityInTime(a_f3BoostVelocity, a_fReachVelocityDuration);

	    // Notify of the boost begin
        m_rEventComponent.RaiseEvent(gkBoostEvent.BoostBegin);
    }

    /// \brief  Called just after the game begin to play
    void Start()
    {
	    // Grab the owner velocity controller
	    m_rVelocityController = GetComponent<gkVelocityController>();
		
		// Grab the event component
		m_rEventComponent = GetComponent<gkEventComponent>();
    }

    /// \brief  Called each frame
    void Update()
    {	
	    // Update the boost
	    if(m_bBoosting)
	    {
		    UpdateBoost();
	    }
    }

    /// \brief  Try to reach the desired velocity
    void UpdateBoost()
    {
	    if(m_bInfinite == false)
	    {
		    if(m_fBoostTimeLeft > 0.0f)
		    {
			    // Decrease the boost time
			    m_fBoostTimeLeft -= Time.deltaTime;
		    }
		    else
		    {
			    // Stop the boost
			    m_fBoostTimeLeft = 0.0f;
			    m_bBoosting = false;
    			
			    // Return to normal velocity
			    m_rVelocityController.SetDesiredVelocityInTime(m_f3NormalVelocity, m_fReturnToNormalVelocityDuration);
    			
			    // Notify of the boost end
			    m_rEventComponent.RaiseEvent(gkBoostEvent.BoostEnd);
		    }
	    }
    }
}